package com.ts.api.module.api.service;

import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.module.api.convert.core.http.client.ApiHttpMessage;
import com.ts.api.module.api.convert.org.model.RespOrgPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformFederateForm;
import com.ts.api.module.api.convert.platform.entity.RespPlatformMultiPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformPhoneMd5DataExchange;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiCheckHistoryUserBO;
import com.ts.api.module.api.entity.bo.ApiParameterBO;
import com.ts.api.module.api.entity.bo.ApiPreRequiredBO;
import com.ts.api.module.api.entity.bo.ApiRequiredFlowBO;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPlanFieldPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 *  API业务验证方法
 *
 *  @author Pan
 */
public interface ApiBizRequiredService {

    /**
     *  获取该手机号码的流程数据
     *  如果出现失败流程则抛出异常
     *
     *  @param  apiClient 渠道客户端ID
     *  @param  phoneMd5  手机号码md5
     *  @return List
     */
    List<ProductApplyFlowPO> existFailFlow(String apiClient, String phoneMd5);

    /**
     *  渠道前置验证参数
     *  撞库、进件前置参数校验
     *  <br>必填条件验证
     *
     *  @param apiPreRequiredBO  前置验证业务实体
     *  @return ApiParameterBO
     */
    ApiParameterBO preRequiredParam(ApiPreRequiredBO apiPreRequiredBO);

    /**
     *  渠道前置手机号掩码8位验证参数
     *  撞库、进件前置参数校验
     *  <br>必填条件验证
     *
     *  @param apiPreRequiredBO  前置验证业务实体
     *  @return ApiParameterBO
     */
    ApiParameterBO preRequiredParamPhoneMask(ApiPreRequiredBO apiPreRequiredBO);

    /**
     *  判断当前时间是否超出计划时间
     *
     *  @author Pan
     *  @param  insertProductApplyFlowPO        流程实体
     *  @param  productPlanPO                   主体计划实体
     *  @param  productApplyFlowStatusEnum      流程枚举
     *  @return boolean
     */
    boolean hasLimitTime(ProductApplyFlowPO insertProductApplyFlowPO, ProductPlanPO productPlanPO, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  判断主体计划是否超出限量
     *
     *  @author Pan
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  productPlanPO               主体计划实体
     *  @param  productApplyFlowStatusEnum  流程枚举
     *  @return boolean
     */
    boolean hasLimitTotal(ProductApplyFlowPO insertProductApplyFlowPO, ProductPlanPO productPlanPO, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  判断该渠道是否被屏蔽
     *
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  productPlanPO               主体计划实体
     *  @param  loanChannelId               当前渠道id
     *  @param  productApplyFlowStatusEnum  流程枚举
     *  @return boolean
     */
    boolean hasChannelFilter(ProductApplyFlowPO insertProductApplyFlowPO, ProductPlanPO productPlanPO, Long loanChannelId, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  此次手机号md5是否存在MD5库中
     *
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  productPlanPO               主体计划实体
     *  @param  phoneMd5                    手机号md5
     *  @param  productApplyFlowStatusEnum  流程枚举
     *  @return boolean
     */
    boolean hasExistMd5Filter(ProductApplyFlowPO insertProductApplyFlowPO, ProductPlanPO productPlanPO, String phoneMd5, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  API渠道版本于平台计划版本是否为同一种类型（全流程对全流程，半流程对半流程）
     *  平台计划版本验证
     *  @param  apiKeyPO        Api渠道实体
     *  @param  productPlanPO   主体计划实体
     *  @return boolean
     */
    boolean requiredApiChannelPlanVersion(ApiKeyPO apiKeyPO, ProductPlanPO productPlanPO);

    /**
     *  验证API渠道中的模式对应
     *  API渠道MD5模式->下游MD5模式
     *
     *  @param  apiKeyPO        Api渠道实体
     *  @param  productPlanPO   主体计划实体
     *  @return boolean
     */
    boolean requiredApiChannelPlanModeVersion(ApiKeyPO apiKeyPO, ProductPlanPO productPlanPO);

    /**
     *  进件-验证是否存在撞库成功流程
     *
     *  @param  apiRequiredFlowBO   API验证流程实体
     *  @return ProductApplyFlowPO
     */
    ProductApplyFlowPO requiredSucDataExchangeFlow(ApiRequiredFlowBO apiRequiredFlowBO);

    /**
     *  根据用户表单验证是否满足机构资质字段
     *  同时满足顺序:
     *      1.计划资质全匹配
     *      2.计划多选其一匹配
     *
     *  @param  listProductPlanFieldPO   机构字段
     *  @param  userForm                 用户表单字段
     *  @return ProductPlanPO
     */
    boolean requiredPlanField(List<ProductPlanFieldPO> listProductPlanFieldPO, Map<String, String> userForm);

    /**
     *  验证获取的计划单价，如果小于当前渠道单价则返回false
     *
     *  @param  productPlanPO     主体计划对象
     *  @param  channelPrice      渠道单价
     *  @return ProductPlanPO
     */
    boolean requiredPlanPrice(ProductPlanPO productPlanPO, BigDecimal channelPrice);

    /**
     *  验证获取的输入的单价，如果小于当前渠道单价则返回false
     *
     *  @param  finalPrice        最终返回价格
     *  @param  channelPrice      渠道单价
     *  @return ProductPlanPO
     */
    boolean requiredPlanPrice(BigDecimal finalPrice, BigDecimal channelPrice);

    /**
     *  验证本次扣款机构余额是否充足
     *
     *  @param  insertProductApplyFlowPO  流程实体
     *  @param  productPlanPO             主体计划实体
     *  @return boolean
     */
    boolean requiredProductAmount(ProductApplyFlowPO insertProductApplyFlowPO, ProductPlanPO productPlanPO, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  进件-验证资质是否与计划相匹配
     *
     *  @param  insertProductApplyFlowPO 流程实体
     *  @param  productPlanPO            主体计划实体
     *  @param  userFormMap              传递用户表单资质
     *  @return boolean
     */
    boolean requiredApplyForm(ProductApplyFlowPO insertProductApplyFlowPO, ProductPlanPO productPlanPO, Map<String, String> userFormMap);

    /**
     *  进件-判断传递城市与流程城市是否一致
     *
     *  @author Pan
     *  @param  insertProductApplyFlowPO 流程实体
     *  @param  apiUserRequest              API数据实体
     *  @param  sourceCityName           源城市
     *  @return boolean
     */
    boolean requiredApplyCity(ProductApplyFlowPO insertProductApplyFlowPO, ApiUserRequest apiUserRequest, String sourceCityName);

    /**
     *  平台撞库-验证撞库时平台返回信息正确
     *
     *  @param  insertProductApplyFlowPO 流程实体
     *  @param  apiHttpMessage           APIHttp消息类
     *  @param  hasPlatShare             是否平台分润计划
     *  @param  productPlanPO            平台计划
     *  @return ApiPlatFormDataExchange
     */
    RespPlatformPhoneMd5DataExchange requiredPlatformDataExchange(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage,
                                                                  boolean hasPlatShare, ProductPlanPO productPlanPO);

    /**
     *  平台撞库-验证撞库时平台返回信息正确-手机号八位掩码
     *
     *  @param  insertProductApplyFlowPO 流程实体
     *  @param  apiHttpMessage           APIHttp消息类
     *  @param  hasPlatShare             是否平台分润计划
     *  @param  productPlanPO            平台计划
     *  @return ApiPlatFormDataExchange
     */
    RespPlatformMultiPhoneMaskDataExchange requiredPlatformPhoneMaskDataExchange(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage,
                                                                                 boolean hasPlatShare, ProductPlanPO productPlanPO);

    /**
     *  平台撞库-验证撞库时平台返回信息正确-联登模式
     *
     *  @param  insertProductApplyFlowPO 流程实体
     *  @param  apiHttpMessage           APIHttp消息类
     *  @return ApiPlatFormFederate
     */
    RespPlatformFederateForm requiredPlatFormFederateDataExchange(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage);

    /**
     *  机构撞库-转换返回实体类
     *
     *  @param  insertProductApplyFlowPO 流程实体
     *  @param  apiHttpMessage           APIHttp消息类
     *  @param  hasPlatShare             是否平台分润计划
     *  @param  productPlanPO            平台计划
     *  @return ApiOrgMaskDataExchange
     */
    RespOrgPhoneMaskDataExchange respOrgDataExchange(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage,
                                                     boolean hasPlatShare, ProductPlanPO productPlanPO);

    /**
     *  手机号-空号、错误号检测
     *
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  productPlanPO               主体计划实体
     *  @param  phone                       手机号
     *  @return boolean
     */
    boolean requiredPhoneStatus(ProductApplyFlowPO insertProductApplyFlowPO, ProductPlanPO productPlanPO, String phone);

    /**
     *  返回HTTP是否为超时
     *
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  apiHttpMessage              APIHttp消息类
     *  @param  productApplyFlowStatusEnum  流程枚举
     *  @return boolean
     */
    boolean hasHttpTimeOut(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  机构方返回HTTP是否为异常
     *
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  apiHttpMessage              API机构Http消息类
     *  @param  enableInsert                是否开启插入流程
     *  @param  productApplyFlowStatusEnum  流程枚举
     *  @return boolean
     */
    boolean hasHttpExp(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage, boolean enableInsert, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  计划类-返回业务消息是否为成功
     *
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  apiHttpMessage              API机构Http消息类
     *  @param  enableInsert                是否开启插入流程
     *  @param  productApplyFlowStatusEnum  流程枚举
     *  @return boolean
     */
    boolean hasHttpRespBizSuc(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage, boolean enableInsert, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  通知类-返回业务消息是否为成功
     *
     *  @param  insertProductApplyFlowPO    流程实体
     *  @param  apiHttpMessage              API机构Http消息类
     *  @param  productApplyFlowStatusEnum  流程枚举
     *  @return boolean
     */
    boolean hasNoticeHttpRespSuc(ProductApplyFlowPO insertProductApplyFlowPO, ApiHttpMessage apiHttpMessage, ProductApplyFlowStatusEnum productApplyFlowStatusEnum);

    /**
     *  检测该用户是否存在历史库-md5模式
     *
     *  @param  apiCheckHistoryUserBO   检测业务实体
     *  @return boolean
     */
    boolean existHistoryUser(ApiCheckHistoryUserBO apiCheckHistoryUserBO);

    /**
     *  检测该用户是否存在历史库-掩码模式
     *
     *  @param  apiCheckHistoryUserBO   检测业务实体
     *  @return boolean
     */
    List<ChannelUserRegisterPO> existHistoryUserPhoneMask(ApiCheckHistoryUserBO apiCheckHistoryUserBO);
}
